package com.music.lib

import com.android.build.api.transform.*
import com.android.build.gradle.internal.pipeline.TransformManager
import com.android.utils.FileUtils

/**
 * @author Afra55
 * @date 2020/8/7
 * A smile is the best business card.
 * 没有成绩，连呼吸都是错的。
 */
class AsmClassTransform : Transform() {
    /**
     * Returns the unique name of the transform.
     *
     *
     * This is associated with the type of work that the transform does. It does not have to be
     * unique per variant.
     */
    override fun getName(): String {
        // 指定 Transform 任务的名字，区分不同的 Transform 任务
        return this::class.simpleName!!
    }

    /**
     * Returns the type(s) of data that is consumed by the Transform. This may be more than
     * one type.
     *
     * **This must be of type [QualifiedContent.DefaultContentType]**
     */
    override fun getInputTypes(): MutableSet<QualifiedContent.ContentType> {
        // 指定 Transform 处理文件的类型，一般 返回 CONTENT_CLASS 即Class文件
        return TransformManager.CONTENT_CLASS
    }

    /**
     * Returns whether the Transform can perform incremental work.
     *
     *
     * If it does, then the TransformInput may contain a list of changed/removed/added files, unless
     * something else triggers a non incremental run.
     */
    override fun isIncremental(): Boolean {
        // 是否支持增量编译
        return false
    }

    /**
     * Returns the scope(s) of the Transform. This indicates which scopes the transform consumes.
     */
    override fun getScopes(): MutableSet<in QualifiedContent.Scope> {
        // 表示 Transform 作用域，SCOPE_FULL_PROJECT 表示整个工程的 class 文件，包括子项目和外部依赖
        return TransformManager.SCOPE_FULL_PROJECT
    }


    override fun transform(transformInvocation: TransformInvocation?) {
        super.transform(transformInvocation)
        // 整个类的核心， 获取输入的 class 文件，对 class 文件进行修改，最后输出修改后的 class 文件
        transformInvocation?.inputs?.forEach{input ->
            // 遍历文件夹
            input.directoryInputs.forEach {dirInput ->
                // 修改字节码
                // ...
                // 获取输出路径
                val outputLocationDir = transformInvocation.outputProvider.getContentLocation(
                    dirInput.name,
                    dirInput.contentTypes,
                    dirInput.scopes,
                    Format.DIRECTORY
                )
                // 把 input 文件夹复制到 output 文件夹，以便下一级Transform处理
                FileUtils.copyDirectory(dirInput.file, outputLocationDir)

            }


            // 遍历 jar 包
            input.jarInputs.forEach {jarInput ->
                // 修改字节码
                // ...
                // 获取输出路径
                val outputLocationDir = transformInvocation.outputProvider.getContentLocation(
                    jarInput.name,
                    jarInput.contentTypes,
                    jarInput.scopes,
                    Format.JAR
                )
                // 把 input jar 包复制到 output 文件夹，以便下一级transform处理
                FileUtils.copyDirectory(jarInput.file, outputLocationDir)

            }
        }

    }
}